import cv2
import numpy
import copy
import matplotlib.pyplot as plt

##图片路径
filename = r'./Lena.jpg'
img = cv2.imread(filename)

#1. 以Lena为原始图像，通过OpenCV实现平均滤波，高斯滤波及中值滤波，比较滤波结果。
# 均值滤波
cv2.imshow("JZLB",cv2.blur(img, (5,5)))
# 高斯滤波
cv2.imshow("GSLB",cv2.GaussianBlur(img,(5,5),0))
# 中值滤波
cv2.imshow("ZZLB",cv2.medianBlur(img, 5))
# 双边滤波
cv2.imshow("SBLB",cv2.bilateralFilter(img,9,75,75))
cv2.waitKey()

##均值滤波图像中的边缘信息以及特征信息“模糊”，高斯和总之则对特征点保护较好，但中值计算时间较长

##
#2. 以Lena为原始图像，通过OpenCV使用Sobel及Canny算子检测，比较边缘检测结果。
#高斯模糊
blurred = cv2.GaussianBlur(img, (3, 3), 0)
#转换为灰度图
gray_blurred=cv2.cvtColor(blurred,cv2.COLOR_BGR2GRAY)#将图片转换为灰度图
cv2.imshow('GRAY', gray_blurred)    #显示灰度图片

#使用Canny算子进行边缘检测
cannny = cv2.Canny(gray_blurred, 10, 300)
cv2.imshow('Canny', cannny)    #显示原始图片

#使用sobel算子进行边缘检测
sobel = cv2.Sobel(gray_blurred,-1,1,0,ksize=3)
cv2.imshow('sobel', sobel)    #显示原始图片

#使用laplacian算子进行边缘检测
laplacian = cv2.Laplacian(gray_blurred,-1)
cv2.imshow('laplacian', laplacian)    #显示原始图片

cv2.waitKey()
###canny对复杂边缘处理较好

#3. 在OpenCV安装目录下找到课程对应演示图片(安装目录\sources\samples\data)，首先计算灰度直方图，进一步使用大津算法进行分割，并比较分析分割结果。
gray=cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)#将原始图片转换为灰度图
plt.hist(gray.ravel(), 256, [0, 256]) #计算灰度直方图
plt.show()
_,dst = cv2.threshold(gray, 0, 255, cv2.THRESH_OTSU) #使用大津算法进行图像二值化
cv2.imshow('DZSF', dst)
cv2.waitKey()

##算法对渐变区域处理较差，但可以分离前后背景

#4. 使用米粒图像，分割得到各米粒，首先计算各区域(米粒)的面积、长度等信息，进一步计算面积、长度的均值及方差，分析落在3sigma范围内米粒的数量。
rice = cv2.imread(r'./rice.png')
gray_rice = cv2.cvtColor(rice,cv2.COLOR_BGR2GRAY) #转换为灰度图
_,dw = cv2.threshold(gray_rice, 0, 255, cv2.THRESH_OTSU) #使用大津算法进行阈值化
element = cv2.getStructuringElement(cv2.MORPH_CROSS,(3, 3))
bw = cv2.morphologyEx(dw,cv2.MORPH_OPEN,element)  #开运算，减少噪声

seg = copy.deepcopy(bw)
bin,cnts, hier =cv2.findContours(seg, cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_SIMPLE) #找轮廓
count = 0
for i in range(len(cnts),0,-1):
    c = cnts[i-1]
    area = cv2.contourArea(c)
    if area <10:
        continue
    count += 1
    print("blob",i,":",area)

    x, y, w, h = cv2.boundingRect(c)
    cv2.rectangle(rice,(x,y),(x+w, y+h),(0,0,0xff),1)
    cv2.putText(rice,str(count),(x,y),cv2.FONT_HERSHEY_PLAIN,0.5,(0,0xff,0))

print("米粒数量：", count)
cv2.imshow("rice",rice)
cv2.imshow("yuzhitu",bw)
cv2.waitKey()

###米粒数量为93
'''
#扩展作业：
#5. 使用棋盘格及自选风景图像，分别使用SIFT、FAST及ORB算子检测角点，并比较分析检测结果。
#(可选)使用Harris角点检测算子检测棋盘格，并与上述结果比较。
qipan = cv2.imread(r'./qipan.png')
qipan_gray = cv2.cvtColor(qipan,cv2.COLOR_BGR2GRAY)

sift = cv2.xfeatures2d.SIFT_create()
kp,des = sift.detectAndCompute(qipan,None)
cv2.imshow('qipan_gray',qipan_gray)
img1=cv2.drawKeypoints(qipan,kp,qipan,color=(255,0,255))
cv2.imshow('point',img1)
cv2.waitKey(0)

#FAST算子
fast = cv2.FastFeatureDetector_create()
kp = fast.detect(qipan,None)
img2 = cv2.drawKeypoints(qipan, kp, None, color=(255,0,0))
cv2.imshow('fast_true',img2)
cv2.waitKey(0)

#ORB算子
def drawMatches(img1, kp1, img2, kp2, matches):
    rows1 = img1.shape[0]
    cols1 = img1.shape[1]
    rows2 = img2.shape[0]
    cols2 = img2.shape[1]

    out = np.zeros((max([rows1,rows2]),cols1 + cols2, 3),dtype = 'uint8')
    #拼接图像
    out[:rows1, :cols1] = np.dstack([img1, img1,img1])
    out[:rows2, cols1:] = np.dstack([img2, img2,img2])

    for mat in matches:
        img1_idx = mat.queryIdx
        img2_idx = mat.trainIdx

        (x1,y1) = kp1[img1_idx].pt
        (x2,y2) = kp2[img2_idx].pt
        #绘制匹配点
        cv2.circle(out, (int(x1),int(y1)),4,(255,255,0),1)
        cv2.circle(out,(int(x2)+cols1,int(y2)),4,(0,255,255),1)

        cv2.line(out,(int(x1),int(y1)),(int(x2)+cols1,int(y2)),(255,0,0),1)

    return out

detector = cv2.ORB_create()

kp1 = detector.detect(img1,None)
kp2 = detector.detect(img2,None)
kp1,des1 = detector.compute(img1,kp1)
kp2,des2 = detector.compute(img2,kp2)

bf = cv2.BFMatcher(cv2.NORM_HAMMING,crossCheck = True)
matches = bf.match(des1,des2)
img3 = drawMatches(img1,kp1,img2,kp2,matches[:50])
# img3 = cv2.drawKeypoints(img1,kp,None,color = (0,255,0),flags = 0)

cv2.imwrite("orbTest.jpg",img3)
cv2.imshow('orbTest',img3)
cv2.waitKey(0)
'''